#pragma once
#include <iostream>
#include <cstring>
#include <string>
#include <cerrno>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <signal.h>
#include <sys/wait.h>
#include <pthread.h>
#include "Common.hpp"
#include "Log.hpp"
using namespace LogModule;
const uint16_t gport = 8080;
const int BACKLOG = 8;
class Server
{
private:
    struct ServerData
    {
        int sockfd;
        Server *server;
    };

public:
    Server(uint16_t port = gport)
        : _port(port), _isrunning(false)
    {
    }
    void Init()
    {
        // 创建TCP套接字               //面向字节流
        _listensockfd = socket(AF_INET, SOCK_STREAM, 0);
        if (_listensockfd < 0)
        {
            LOG(Loglevel::FATAL) << "socket filed";
            Die(SOCKET_ERROR);
        }
        LOG(Loglevel::INFO) << "socket success,sockfd:" << _listensockfd;
        // 填充网络信息
        struct sockaddr_in local;
        memset(&local, 0, sizeof(local));
        local.sin_family = AF_INET;
        local.sin_port = htons(_port);
        // 云服务器不允许绑定IP,所以要填任意IP
        local.sin_addr.s_addr = INADDR_ANY;
        int n = bind(_listensockfd, CONV(&local), sizeof(local));
        if (n < 0)
        {
            LOG(Loglevel::FATAL) << "bind filed";
            Die(BIND_ERROR);
        }
        LOG(Loglevel::INFO) << "bind success,sockfd:" << _listensockfd;
        // TCP是面向连接的,需要TCP随时随地等待被连接
        // 要将_listensockid设为监听状态
        n = listen(_listensockfd, BACKLOG); // 排队数,一般为4,8,16,32
        if (n < 0)
        {
            LOG(Loglevel::FATAL) << "listen filed";
            Die(LISTEN_ERROR);
        }
        LOG(Loglevel::INFO) << "listen success,sockfd:" << _listensockfd;
    }
    static void* ThreadEntry(void *args)  //这里要加static避免隐含的this指针
    {
        pthread_detach(pthread_self()); // 线程分离
        ServerData *tmp = (ServerData *)args;
        tmp->server->HandlerRequest(tmp->sockfd);
        // data是new申请出来的,不用时要进行资源释放
        delete tmp;
        return nullptr;
    }
    void Start()
    {
        _isrunning = true;
        while (_isrunning)
        {
            // TCP不能直接进行通信,要先建立连接
            sockaddr_in peer;
            socklen_t len = sizeof(peer);
            int sockfd = accept(_listensockfd, CONV(&peer), &len);
            if (sockfd < 0)
            {
                LOG(Loglevel::ERROR) << "accept filed" << strerror(errno);
            }
            LOG(Loglevel::INFO) << "accept success,sockfd:" << sockfd;
            // 多线程版本
            // 线程之间的文件描述符是共享的,所以不用关闭文件描述符
            pthread_t tid;
            ServerData *data = new ServerData;
            data->server = this;
            data->sockfd = _listensockfd;
            pthread_create(&tid, nullptr, ThreadEntry, data); //HandlerRequest封装在类里,必须使用结构体把this(要使用类里的方法)和fd一块传过去
        }
    }
    void HandlerRequest(int sockfd)
    {
        LOG(Loglevel::INFO) << "HandlerRequest,sockfd:" << sockfd;
        char inbuffer[1024];
        while (true)
        {
            int n = recv(sockfd, inbuffer, sizeof(inbuffer) - 1, 0);
            if (n > 0)
            {
                inbuffer[n] = 0; // 确保inbuffer以null结尾
                int n = send(sockfd, inbuffer, sizeof(inbuffer), 0);
                (void)n;
            }
        }
    }
    void Stop()
    {
        _isrunning = false;
    }
    ~Server()
    {
    }

private:
    int _listensockfd;
    uint16_t _port;
    bool _isrunning;
};